pytest 學習指南(基礎篇)
基本操作
學習 pytest 可以大幅提升編寫單元測試的效率,並輕鬆整合至 CI/CD 工作流程中。建議從簡單的測試開始,逐步深入探索 pytest 的各種進階功能。
1. 安裝 pytest
在 Python 中使用 pytest 之前,必須先安裝它。可以通過 pip 來安裝:
pip install pytest
2. 撰寫一個簡單的測試案例
pytest 可以讓你輕鬆撰寫測試案例。假設有一個名為 math_func.py 的檔案,其中有一個簡單的函數:
# math_func.py def add(x, y): return x + y
可以撰寫一個測試檔案,例如 test_math_func.py:
# test_math_func.py from math_func import add def test_add(): assert add(1, 2) == 3 assert add(0, 0) == 0 assert add(-1, 1) == 0
3. 執行測試
在專案的根目錄下執行 pytest,其中 -v
表示詳細模式,顯示每個測試案例的結果。
pytest -v
pytest 會自動偵測以 test_ 開頭的檔案以及以 test_ 開頭的函數並執行它們。結果會詳細地顯示測試過程與結果。
pytest 會自動解析錯誤訊息,使得測試失敗時提供更具可讀性的輸出。以下範例手動加入一個失敗的測試,pytest 會清楚告訴你預期值和實際結果的差異。
def test_add_fail(): assert add(1, 2) == 0
接著在該目錄下執行 pytest -v
後即可看到這個測試項目有紅色的 fail。
pytest 常用指令選項
選項 | 說明 | 用法範例 |
---|---|---|
-v |
詳細模式,顯示每個測試案例的結果 | pytest -v |
-s |
顯示測試過程中的標準輸出,如 print() 內容 |
pytest -s |
-k <expression> |
僅運行符合條件的測試案例 | pytest -k "test_function_name" |
-m <mark> |
僅運行特定標記的測試案例 | pytest -m "slow" |
-x |
首次測試失敗時停止測試執行 | pytest -x |
--tb=short |
縮短錯誤的 traceback 訊息,讓報告更簡潔 | pytest --tb=short |
--maxfail=<num> |
遇到指定數量的測試失敗後停止執行測試 | pytest --maxfail=2 |
--html=<file> |
生成 HTML 格式的測試報告(需要 pytest-html 插件) |
pytest --html=report.html |
--junitxml=<file> |
生成 JUnit XML 格式的測試報告 | pytest --junitxml=report.xml |
--durations=<num> |
列出運行時間最長的 <num> 個測試案例 |
pytest --durations=5 |
--cov=<module_or_path> |
生成程式碼覆蓋率報告(需要 pytest-cov 插件) |
pytest --cov=my_module |
--reuse-db |
重新使用上次的資料庫測試環境(適用於測試資料庫環境) | pytest --reuse-db |
執行測試並生成 HTML 報告
我們可以將測試結果直接產生 report.html,只需要安裝 pytest-html 套件。
pip install pytest-html
接著執行測試並生成 HTML 報告,使用 --html 選項來指定報告的檔案名稱。此外,也可以同時搭配上方表格中的其他常用指令一起使用,以更靈活地控制測試流程。
pytest -v --html=report.html
這樣測試完成後,pytest 會在專案目錄下生成一個 report.html,裡面包含測試結果的詳細報告。
上述方法生成的報告,CSS 是獨立的,當分享報告時樣式可能會遺失。為了更好地分享並通過郵件展示報告,可以將 CSS 樣式合併到 HTML 中。
pytest --html=report.html --self-contained-html
使用 pytest 的進階功能
pytest 常用標記
標記 | 說明 | 用法範例 |
---|---|---|
@pytest.mark.skip |
跳過測試案例 | @pytest.mark.skip(reason="Not implemented") |
@pytest.mark.xfail |
預期失敗的測試案例 | @pytest.mark.xfail(raises=ZeroDivisionError) |
@pytest.mark.parametrize |
參數化測試,允許使用多組參數測試同一函數 | @pytest.mark.parametrize("a,b", [(1, 2), (3, 4)]) |
@pytest.fixture |
定義測試前置環境 | @pytest.fixture |
(1) pytest.fixture
fixture 可以用來設置測試前的準備步驟,例如初始化資料庫或建立物件:
import pytest @pytest.fixture def sample_data(): return {"key": "value"} def test_sample_data(sample_data): assert sample_data["key"] == "value"
(2) 測試多組輸入
可以使用 pytest.mark.parametrize 來測試多組輸入:
import pytest from math_func import add @pytest.mark.parametrize("a, b, expected", [(1, 2, 3), (0, 0, 0), (-1, 1, 0)]) def test_add_multi(a, b, expected): assert add(a, b) == expected